﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

using CommerceML.Version205;
using IBS;
using Interfaces;

using EdexClient;

namespace CommerceML2IBS
{
    public class IntegrationContext
    {
        private string IbsConnectionString { get; set; }
        private IbsDataContext db { get; set; }

        public IntegrationContext(string IbsConnectionString)
        {
            this.IbsConnectionString = IbsConnectionString;
            this.db = new IbsDataContext(this.IbsConnectionString);
        }

        public void Process(string uri)
        {
            this.Process(uri, null);
        }

        public void Process(string uri, SaleOrder defaultDocument)
        {
            var data = this.GetCommerceML(uri);

            data.Items.ToList().ForEach(r =>
            {
                if (r is Документ)
                    this.ProcessDocumentN((Документ)r, defaultDocument);

                if (r is Каталог)
                    this.ProcessCatalog((Каталог)r);

                if (r is ПакетПредложений)
                    this.ProcessPackage((ПакетПредложений)r);

            });

        }

        private void ProcessDocumentN(Документ entity, ISaleOrder defaultDocument)
        {
            try
            {
                var document = new SaleOrder();
                document.OUTER_KEY = Guid.Parse(entity.Ид);
                document.DOC_DATE = entity.Дата;               
                document.DOC_NUMBER = entity.Номер;
                document.TOTAL_AMOUNT = entity.Сумма;
                document.LINECOUNT = entity.Товары.Count();
                document.NOTE = String.IsNullOrEmpty(entity.Комментарий) ? String.Empty : entity.Комментарий;
                document.TAX_AMOUNT = 0;

                /// Получатель
                if (entity.Контрагенты.Any(r => r.Роль == РольТип.Покупатель))
                {
                    var store = entity.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Покупатель).Склад;
                    document.LOCATION_KEY = int.Parse(store.Ид);
                }
                else
                {
                    throw new Exception("Не указан Покупатель");
                }

                /// Поставщик
                if (entity.Контрагенты.Any(r => r.Роль == РольТип.Продавец))
                {
                    var supplier = entity.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Продавец);
                    //document.SupplierId = db.GetSupplierByGuid(Guid.Parse(supplier.Ид)).ID_Record;
                    document.COMPANY_KEY = int.Parse(supplier.Ид);
                }
                else
                {
                    throw new Exception("Не указан поставщик");
                }

                /// Позиции
                /// 
                document.SaleOrderItems = entity.Товары.Select(r =>
                {
                    var item = new SaleOrderItem();
                    
                    item.ITEM_KEY = long.Parse(r.Ид);
                    item.PRICE = r.ЦенаЗаЕдиницу;
                    item.ACTUAL_PRICE = 0; //подставляется в процедуре
                    item.QUANTITY = r.Количество;
                    
                    /// С налогами пока не понятно
                    /// нужны примеры
                    /// item.TaxPercent = r.Налоги                    /// 
                    
                    //item.DISCOUNT = r.
                    //item.TOTAL = r.
                    
                    return item;
                }).ToList();

                var doc_id = db.SaveSaleOrder(document);
                

                EdexClient.API_SESSION session = new API_SESSION();
                string pathString = "http://localhost:1953/edex/";
                var edex = new EdexClient.EdexContext(pathString);
                session = edex.GetSession("tnk@tnk.ru", "12345");
                edex.ChangeCompany("E4EFEE0D-0162-4FE8-B3A8-22DFFDDBA32B", session.APIKEY); //PETROL  
                session = edex.GetSession("tnk@tnk.ru", "12345");

                edex.SetIncomingNumber(document.OUTER_KEY, doc_id.ToString(), session.APIKEY);


            



            }
            catch (Exception ex)
            {

            }
        }

        private void ProcessDocument(Документ entity, IDelivery defaultDocument)
        {
            try
            {
                var document = new Delivery();

                document.BusinessDate = entity.Дата;
                document.DeliveryDate = entity.Дата;
                document.DeliveryNumber = entity.Номер;
                document.ExternalDeliveryNumber = entity.Номер;

                /// Позиции
                /// 
                document.DeliveryItems = entity.Товары.Select(r =>
                {
                    var item = new DeliveryItem();

                    item.Quantity = r.Количество;

                    item.AveragePrice = r.ЦенаЗаЕдиницу;
                    item.CurrentPrice = r.ЦенаЗаЕдиницу;
                    item.RetailPrice = r.ЦенаЗаЕдиницу;

                    /// С налогами пока не понятно
                    /// нужны примеры
                    /// item.TaxPercent = r.Налоги

                    /// Накладные по топливным поставкам будут? 
                    item.Weight = 0;

                    //item.ItemId = db.GetItemByGuid(Guid.Parse(r.Ид)).ID_Record;
                    item.ItemId = long.Parse(r.Ид);

                    return item;
                }).ToList();

                /// Получатель
                if (entity.Контрагенты.Any(r => r.Роль == РольТип.Покупатель))
                {
                    var store = entity.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Покупатель).Склад;
                    document.StoreId = int.Parse(store.Ид);
                }
                else
                {
                    throw new Exception("Не указан Покупатель");
                }

                /// Поставщик
                if (entity.Контрагенты.Any(r => r.Роль == РольТип.Продавец))
                {
                    var supplier = entity.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Продавец);
                    //document.SupplierId = db.GetSupplierByGuid(Guid.Parse(supplier.Ид)).ID_Record;
                    document.SupplierId = int.Parse(supplier.Ид);
                }
                else
                {
                    throw new Exception("Не указан поставщик");
                }

                /// Значения в IBS
                /// 1	Приход
                /// 2	Расход
                /// 4	Возврат
                /// 5	Продажа
                //switch(entity.ХозОперация)
                //{
                //    case ХозОперацияТип.Возвраткомиссионноготовара:
                //        document.TypeId = 4;
                //        break;
                //    case ХозОперацияТип.Возвраттовара:
                //        document.TypeId = 4;
                //        break;
                //    case ХозОперацияТип.Отпусктовара:
                //        document.TypeId = 2;
                //        break;
                //    case ХозОперацияТип.Передачатоваранакомиссию:
                //        document.TypeId = 2;
                //        break;
                //    case ХозОперацияТип.Счетфактура:
                //        document.TypeId = 1;
                //        break;
                //}

                document.TypeId = 1;

                /// Установка дефолтных значений
                if (defaultDocument != null)
                {
                    if (defaultDocument.BusinessDate != DateTime.MinValue)
                        document.BusinessDate = defaultDocument.BusinessDate;

                    if (defaultDocument.DeliveryDate != DateTime.MinValue)
                        document.DeliveryDate = defaultDocument.DeliveryDate;

                    if (defaultDocument.DeliveryNumber != null)
                        document.DeliveryNumber = defaultDocument.DeliveryNumber;

                    if (defaultDocument.ExternalDeliveryNumber != null)
                        document.ExternalDeliveryNumber = defaultDocument.ExternalDeliveryNumber;

                    if (defaultDocument.StoreId != 0)
                        document.StoreId = defaultDocument.StoreId;

                    if (defaultDocument.SupplierId != 0)
                        document.SupplierId = defaultDocument.SupplierId;

                    if (defaultDocument.TypeId != 0)
                        document.TypeId = defaultDocument.TypeId;
                }


                db.SaveDelivery(document, 9900000000);
            }
            catch (Exception ex)
            {

            }

        }

        private void ProcessCatalog(Каталог entity) { }

        private void ProcessPackage(ПакетПредложений entity) { }

        private CommerceML.Version205.КоммерческаяИнформация LoadCommerceML(string path)
        {
            // Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

            // Create the XmlReader object.
            XmlReader reader = XmlReader.Create(path, settings);

            XmlSerializer serializer = new XmlSerializer(typeof(CommerceML.Version205.КоммерческаяИнформация));
            var sd = (CommerceML.Version205.КоммерческаяИнформация)serializer.Deserialize(reader);
            reader.Close();

            return sd;
        }

        public CommerceML.Version205.КоммерческаяИнформация GetCommerceML(string xmlData)
        {
            
            //using (var reader = System.Xml.XmlReader.Create(uri))
            using (var reader = System.Xml.XmlReader.Create(new System.IO.StringReader(xmlData)))
            {
                var serializer
                    = new System.Xml.Serialization.XmlSerializer(typeof(CommerceML.Version205.КоммерческаяИнформация));

                return (CommerceML.Version205.КоммерческаяИнформация)serializer.Deserialize(reader);
            }
        }

        // Display any warnings or errors.
        private static void ValidationCallBack(object sender, ValidationEventArgs args)
        {
            if (args.Severity == XmlSeverityType.Warning)
                Console.WriteLine("\tWarning: Matching schema not found.  No validation occurred." + args.Message);
            else
                Console.WriteLine("\tValidation error: " + args.Message);
        }


    }

    public class SaleOrder : ISaleOrder
    {
        public Guid OUTER_KEY { get; set; }
        public String DOC_NUMBER { get; set; }
        public DateTime DOC_DATE { get; set; }
        public Int64 COMPANY_KEY { get; set; }
        public Int64 LOCATION_KEY { get; set; }
        public Int32 LINECOUNT { get; set; }
        public Decimal TOTAL_AMOUNT { get; set; }
        public Decimal TAX_AMOUNT { get; set; }
        public String NOTE { get; set; }
        public IEnumerable<ISaleOrderLine> SaleOrderItems { get; set; }
        public SaleOrder()
        {
            this.SaleOrderItems = new List<SaleOrderItem>();
        }
    }

    public class SaleOrderItem : ISaleOrderLine
    {
        public Int64 ITEM_KEY { get; set; }
        public Decimal PRICE { get; set; }
        public Decimal ACTUAL_PRICE { get; set; }
        public Decimal DISCOUNT { get; set; }
        public Decimal QUANTITY { get; set; }
        public Decimal TOTAL { get; set; }        
    }



    public class Delivery : IDelivery
    {
        public DateTime BusinessDate { get; set; }
        public DateTime DeliveryDate { get; set; }
        public int StoreId { get; set; }
        public int SupplierId { get; set; }
        public string DeliveryNumber { get; set; }
        public string ExternalDeliveryNumber { get; set; }
        public int TypeId { get; set; }
        public IEnumerable<IDeliveryItem> DeliveryItems { get; set; }

        public Delivery()
        {
            this.DeliveryItems = new List<DeliveryItem>();
        }
    }

    public class DeliveryItem : IDeliveryItem
    {
        public Int64 ItemId { get; set; }
        public decimal Quantity { get; set; }
        public decimal CurrentPrice { get; set; }
        public decimal RetailPrice { get; set; }
        public decimal AveragePrice { get; set; }
        public int TaxPercent { get; set; }
        public double Weight { get; set; }
    }



    public class IncomingInvoices
    { 
        public Guid GUID_RECORD { get; set; }        
        public string DOC_NUMBER { get; set; }        
    }

}
